package com.yuanmei.views;

import android.content.Context;
import android.os.Environment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.yuanmei.common.Utils;
import com.yuanmei.datas.DBUtils;
import com.yuanmei.model.StockItem;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static android.os.Environment.MEDIA_MOUNTED;

public class StockListAdapter extends BaseAdapter {
    private final static String TAG = StockListAdapter.class.getName();

    private Context mContext;

    private List<StockItem> mCurrentStockList;
    private List<StockItem> mAttentionList;
    private List<StockItem> mPreChooseList;
    private List<StockItem> mProfileIndexStockList;
    private List<StockItem> mMarketIndexList;

    private String mPreChooseListFilePath;
    private String mAttentionListFilePath;
    private String mProfileIndexStockListPath;

    public enum DataListType {
        PRE_CHOOSE_LIST,
        ATTENTION_LIST,
        MARKET_INDEX_LIST,
        PROFILE_INDEX_LIST,
    }

    private final class ItemViewHolder {
        private TextView name;
        private TextView code;
        private TextView price;
        private TextView percent;
        private TextView vol_to_yesterday_percent;
        private TextView vol_to_ma5_percent;
        private TextView vol_to_ma20_percent;
        private TextView net_asset_profit;
        private TextView price_earnings_ratio;
        private TextView industry;
    }

    StockListAdapter(Context context) {
        mContext = context;

        String chooseDir = "choose";
        if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            chooseDir = context.getExternalFilesDir(chooseDir).getAbsolutePath();
        } else {
            chooseDir = context.getFilesDir().getAbsolutePath() + File.separator + chooseDir;
        }

        mPreChooseListFilePath    = chooseDir + File.separator + "pre_choose_list.json";
        mAttentionListFilePath    = chooseDir + File.separator + "attention_list.json";
        mProfileIndexStockListPath = chooseDir + File.separator + "profile_index_list.json";

        mPreChooseList    = new ArrayList<>();
        mAttentionList    = new ArrayList<>();
        mMarketIndexList  = new ArrayList<>();
        mProfileIndexStockList = new ArrayList<>();
        mCurrentStockList = mAttentionList;
    }

    void loadStockListFromFile() {
        mAttentionList = loadStockListByJsonFile(mAttentionListFilePath);
        mMarketIndexList = initMarketIndexList();
        mPreChooseList = loadStockListByJsonFile(mPreChooseListFilePath);
        mProfileIndexStockList = loadStockListByJsonFile(mProfileIndexStockListPath);
    }

    //  对外数据接口
    void setDataList(DataListType dl) {
        if (dl == DataListType.PRE_CHOOSE_LIST) {
            mCurrentStockList = mPreChooseList;
        } else if (dl == DataListType.ATTENTION_LIST) {
            mCurrentStockList = mAttentionList;
        } else if (dl == DataListType.MARKET_INDEX_LIST) {
            mCurrentStockList = mMarketIndexList;
        } else if (dl == DataListType.PROFILE_INDEX_LIST) {
            mCurrentStockList = mProfileIndexStockList;
        }
        notifyDataSetInvalidated();
    }

    private boolean mIsStockCodeAscend = false;

    void sortCurrentListByStockCode() {
        mIsStockCodeAscend = !mIsStockCodeAscend;
        Collections.sort(mCurrentStockList, (o1, o2) -> {
            int res = o1.code().compareTo(o2.code());
            if (res > 0) {
                return mIsStockCodeAscend ? -1 : 1;
            } else if (res < 0) {
                return mIsStockCodeAscend ? 1 : -1;
            } else {
                return 0;
            }
        });
        notifyDataSetInvalidated();
    }

    private boolean mIsPriceSortAscend = false;

    void sortCurrentListByPricePercent() {
        mIsPriceSortAscend = !mIsPriceSortAscend;
        Collections.sort(mCurrentStockList, (o1, o2) -> {
            if (o1.getPercent() > o2.getPercent()) {
                return mIsPriceSortAscend ? -1 : 1;
            } else if (o1.getPercent() < o2.getPercent()) {
                return mIsPriceSortAscend ? 1 : -1;
            }
            return 0;
        });
        notifyDataSetInvalidated();
    }

    private boolean mIsVolumeSortAscend = false;

    void sortCurrentListByVolumePercent() {
        mIsVolumeSortAscend = !mIsVolumeSortAscend;
        Collections.sort(mCurrentStockList, (o1, o2) -> {
            if (o1.getTurnoverPercent() > o2.getTurnoverPercent()) {
                return mIsVolumeSortAscend ? -1 : 1;
            } else if (o1.getTurnoverPercent() < o2.getTurnoverPercent()) {
                return mIsVolumeSortAscend ? 1 : -1;
            }
            return 0;
        });
        notifyDataSetInvalidated();
    }

    private boolean mIsNetAssetOperateProfitRatioSortAscend = false;
    void sortCurrentListByNetAssetsOperateProfitRatio() {
        mIsNetAssetOperateProfitRatioSortAscend = !mIsNetAssetOperateProfitRatioSortAscend;
        Collections.sort(mCurrentStockList, (o1, o2) -> {
            if (o1.getNetAssetsOperatingProfitRatio() > o2.getNetAssetsOperatingProfitRatio()) {
                return mIsNetAssetOperateProfitRatioSortAscend ? -1 : 1;
            } else if (o1.getNetAssetsOperatingProfitRatio() < o2.getNetAssetsOperatingProfitRatio()) {
                return mIsNetAssetOperateProfitRatioSortAscend ? 1 : -1;
            }
            return 0;
        });
        notifyDataSetInvalidated();
    }

    private boolean mIsPriceEarningsRatioSortAscend = false;
    void sortCurrentListByPriceEarningsRatio() {
        mIsPriceEarningsRatioSortAscend = !mIsPriceEarningsRatioSortAscend;
        Collections.sort(mCurrentStockList, (o1, o2) -> {
            if (o1.getPriceEarningRatio() > o2.getPriceEarningRatio()) {
                return mIsPriceEarningsRatioSortAscend ? -1 : 1;
            } else if (o1.getPriceEarningRatio() < o2.getPriceEarningRatio()) {
                return mIsPriceEarningsRatioSortAscend ? 1 : -1;
            }
            return 0;
        });
        notifyDataSetInvalidated();
    }

    private boolean mIsIndustrySortAscend = false;
    void sortCurrentListByIndustry() {
        mIsIndustrySortAscend = !mIsIndustrySortAscend;
        Collections.sort(mCurrentStockList, (o1, o2) -> {
            int res = o1.getIndustryInfo().compareTo(o2.getIndustryInfo());
            if (res > 0) {
                return mIsIndustrySortAscend ? -1 : 1;
            } else if (res < 0) {
                return mIsIndustrySortAscend ? 1 : -1;
            } else {
                return 0;
            }
        });
        notifyDataSetInvalidated();
    }
//
//    List<StockItem> getAllStockList() {
//        List<StockItem> allStocks = new ArrayList<>();
//        allStocks.addAll(mAttentionList);
//        allStocks.addAll(mMarketIndexList);
//        for (StockItem selfItem : mPreChooseList) {
//            if (!allStocks.contains(selfItem)) {
//                allStocks.add(selfItem);
//            }
//        }
//        for (StockItem selfItem : mProfileIndexStockList) {
//            if (!allStocks.contains(selfItem)) {
//                allStocks.add(selfItem);
//            }
//        }
//        return allStocks;
//    }

    List<StockItem> getAttentionList() {
        List<StockItem> attentionListPlus = new ArrayList<>();
        attentionListPlus.addAll(mAttentionList);
        attentionListPlus.addAll(mMarketIndexList);
        return attentionListPlus;
    }

    int getPreChooseListSize() {
        return mPreChooseList.size();
    }
//    List<StockItem> getPreChooseList() {
//        return new ArrayList<>(mPreChooseList);
//    }
//
//    List<StockItem> getProfileList() {
//        return new ArrayList<>(mProfileIndexStockList);
//    }

    List<StockItem> getCurrentList() {
        List<StockItem> stockListPlus = new ArrayList<>(mCurrentStockList);
        if (mCurrentStockList != mMarketIndexList)
            stockListPlus.addAll(mMarketIndexList);
        return stockListPlus;
    }

    int getMarketIndexCount() {
        return mMarketIndexList.size();
    }
    // Json file 相关操作

    boolean saveAttentionListToFile(String srcPath) {
        try {
            OutputStreamWriter osWriter = new OutputStreamWriter(
                    new FileOutputStream(mAttentionListFilePath, false));
            InputStreamReader isReader = new InputStreamReader(new FileInputStream(srcPath));
            StringBuilder sbJson = new StringBuilder();
            char[] rcBuffer = new char[1024];
            int length;
            while ((length = isReader.read(rcBuffer)) != -1) {
                osWriter.write(rcBuffer, 0, length);
                sbJson.append(rcBuffer, 0, length);
            }
            osWriter.close();
            isReader.close();
            mAttentionList = loadStockListByJsonString(sbJson.toString());
            return true;
        } catch (FileNotFoundException e) {
            Log.e(TAG, "copy attention list file not found error:", e);
        } catch (IOException e) {
            Log.e(TAG, "copy attention list file IO error:", e);
        }
        return false;
    }

    synchronized boolean appendPreChooseListFromFile(String srcPath) {
        List<StockItem> addList = loadStockListByJsonFile(srcPath);
        int addCount = addList.size();
        for (StockItem item : addList) {
            if (!mPreChooseList.contains(item)) {
                mPreChooseList.add(item);
            }
        }
        saveStockListToJson(mPreChooseList, mPreChooseListFilePath);
        return (addCount > 0);
    }

    synchronized boolean replacePreChooseListFromFile(String srcPath) {
        try {
            OutputStreamWriter osWriter = new OutputStreamWriter(
                    new FileOutputStream(mPreChooseListFilePath, false));
            InputStreamReader isReader = new InputStreamReader(new FileInputStream(srcPath));
            StringBuilder sbJson = new StringBuilder();
            char[] rcBuffer = new char[1024];
            int length;
            while ((length = isReader.read(rcBuffer)) != -1) {
                osWriter.write(rcBuffer, 0, length);
                sbJson.append(rcBuffer, 0, length);
            }
            osWriter.close();
            isReader.close();
            mPreChooseList = loadStockListByJsonString(sbJson.toString());
            return true;
        } catch (FileNotFoundException e) {
            Log.e(TAG, "copyAIChooseJson FileNotFoundException:", e);
        } catch (IOException e) {
            Log.e(TAG, "copyAIChooseJson IOException:", e);
        }
        return false;
    }

    void appendStockToAttentionList(StockItem newItem) {
        if (!mAttentionList.contains(newItem)) {
            mAttentionList.add(newItem);
            saveStockListToJson(mAttentionList, mAttentionListFilePath);
        }
    }

    void removeStockFromAttentionList(StockItem rmItem) {
        if (mAttentionList.contains(rmItem)) {
            mAttentionList.remove(rmItem);
            saveStockListToJson(mAttentionList, mAttentionListFilePath);
        }
    }

    boolean saveAttentionListToPath(String path) {
        return saveStockListToJson(mAttentionList, path);
    }

    private boolean saveStockListToJson(List<StockItem> list, String path) {
        try {
            JSONObject rootJson = new JSONObject();
            JSONArray stockArray = new JSONArray();
            for (StockItem item : list) {
                JSONObject itemJson = new JSONObject();
                JSONObject stock_info = new JSONObject();
                stock_info.put("name", item.name());
                stock_info.put("code", item.code());
                stock_info.put("fin_info", item.getFinanceInfo());
                stock_info.put("fin_statements", item.getFinancialStatements());
                itemJson.put("stock", stock_info);
                itemJson.put("match", item.getMatchDetail());
                stockArray.put(itemJson);
            }
            rootJson.put("match_stocks", stockArray);

            OutputStream oStream = new FileOutputStream(path, false);
            oStream.write(rootJson.toString().getBytes());
            oStream.close();
            return true;
        } catch (Exception e) {
            Log.e(TAG, "saveStockListToJson fail path=" + path, e);
            return false;
        }
    }

    private List<StockItem> loadStockListByJsonString(String jsonString) {
        List<StockItem> loadList = new ArrayList<>();
        try {
            JSONObject root_json = new JSONObject(jsonString);
            JSONArray match_stocks = root_json.getJSONArray("match_stocks");
            for (int i = 0; i < match_stocks.length(); i++) {
                JSONObject item = match_stocks.getJSONObject(i);

                JSONObject stock_info = item.getJSONObject("stock");
                String match_detail = item.getString("match");

                String name = stock_info.getString("name");
                String code = stock_info.getString("code");
                String fin_statements = stock_info.optString("fin_statements", "Null");
                StockItem newItem = new StockItem(name, code, match_detail, fin_statements,
                        DBUtils.getTdxStockInfoInstance(code),false);
                loadList.add(newItem);
            }
        } catch (JSONException e) {
            Log.w(TAG, "loadStockListByJsonString json parse exception=", e);
        }
        return loadList;
    }

    private List<StockItem> loadStockListByJsonFile(String path) {
        List<StockItem> loadList = new ArrayList<>();
        try {
            InputStreamReader ins = new InputStreamReader(
                    new FileInputStream(path), StandardCharsets.UTF_8);
            BufferedReader br = new BufferedReader(ins);
            String line;
            StringBuilder builder = new StringBuilder();
            while ((line = br.readLine()) != null) {
                builder.append(line);
            }
            br.close();
            ins.close();

            loadList = loadStockListByJsonString(builder.toString());
        } catch (UnsupportedEncodingException | FileNotFoundException e) {
            // 正常情况，无需打印
        } catch (Exception e) {
            Log.w(TAG, "loadStockListByJsonFile error path=" + path, e);
        }
        return loadList;
    }

    private List<StockItem> initMarketIndexList() {
        List<StockItem> mktIdxList = new ArrayList<>();
        mktIdxList.add(new StockItem("上证指数", "000001",  true));
        mktIdxList.add(new StockItem("深证成指", "399001", true));
        mktIdxList.add(new StockItem("深证综指", "399106", true));
        mktIdxList.add(new StockItem("中小板指", "399005", true));
        mktIdxList.add(new StockItem("创业板R", "399606",  true));
        mktIdxList.add(new StockItem("中小300", "399008", true));
        mktIdxList.add(new StockItem("沪深300", "000300",  true));
        return mktIdxList;
    }

    @Override
    public int getCount() {
        return mCurrentStockList.size();
    }

    @Override
    public StockItem getItem(int index) {
        return mCurrentStockList.get(index);
    }

    @Override
    public long getItemId(int arg0) {
        return arg0;
    }

    private View createItemView() {
        ItemViewHolder holder = new ItemViewHolder();
        View itemView = LayoutInflater.from(mContext).inflate(
                R.layout.stock_list_item, null);
        holder.name = itemView.findViewById(R.id.name);
        holder.code = itemView.findViewById(R.id.code);
        holder.price = itemView.findViewById(R.id.price);
        holder.percent = itemView.findViewById(R.id.percent);
        holder.vol_to_yesterday_percent = itemView.findViewById(R.id.vol_to_yestoday);
        holder.vol_to_ma5_percent = itemView.findViewById(R.id.vol_to_ma5);
        holder.vol_to_ma20_percent = itemView.findViewById(R.id.vol_to_ma20);
        holder.net_asset_profit = itemView.findViewById(R.id.npr);
        holder.price_earnings_ratio = itemView.findViewById(R.id.per);
        holder.industry = itemView.findViewById(R.id.industry);

        itemView.setTag(holder);
        return itemView;
    }

    @Override
    public View getView(int position, View itemView, ViewGroup parent) {
        StockItem item = getItem(position);
        if (item == null)
            return null;
        if (itemView == null) {
            itemView = createItemView();
        }
        // Update display
        ItemViewHolder holder = (ItemViewHolder) itemView.getTag();
        holder.name.setText(item.name());
        holder.code.setText(item.code());
        holder.price.setText(item.price());
        holder.percent.setText(item.pricePercent());
        holder.net_asset_profit.setText(Utils.percentToDecimalString(
                item.getNetAssetsOperatingProfitRatio()));
        holder.price_earnings_ratio.setText(String.format("%.2f",item.getPriceEarningRatio()));
        holder.industry.setText(item.getIndustryInfo());

        float predictVolume = item.computePredictVolume();
        String vol2LastPct = item.getVolToLastVolumePercent(predictVolume);
        holder.vol_to_yesterday_percent.setText(vol2LastPct);
        String vol2Ma5pct = item.getVolToMa5Percent(predictVolume);
        holder.vol_to_ma5_percent.setText(vol2Ma5pct);
        String vol2Ma20pct = item.getVolToMa20Percent(predictVolume);
        holder.vol_to_ma20_percent.setText(vol2Ma20pct);

//        updateTimeShareChart(holder, item.getTsChartData());

        return itemView;
    }

    int updateTodayQuotes(ArrayList<String> quotesList) {
        int count = 0;
        for (StockItem item : mAttentionList) {
            if (quotesList.contains(item.netEaseCode())) {
                item.updateTodayQuote();
                count++;
            }
        }

        for (StockItem item : mPreChooseList) {
            if (quotesList.contains(item.netEaseCode())) {
                item.updateTodayQuote();
                count++;
            }
        }

        for (StockItem item : mMarketIndexList) {
            if (quotesList.contains(item.netEaseCode())) {
                item.updateTodayQuote();
                count++;
            }
        }

        for (StockItem item : mProfileIndexStockList) {
            if (quotesList.contains(item.netEaseCode())) {
                item.updateTodayQuote();
                count++;
            }
        }

        return count;
    }

    void updateTodayMinuteTickQuote(String neCode) {
        for (StockItem item : mAttentionList) {
            if (neCode.contains(item.netEaseCode())) {
                item.rebuildTickQuotesFromRealm();
                break;
            }
        }

        for (StockItem item : mPreChooseList) {
            if (neCode.contains(item.netEaseCode())) {
                item.rebuildTickQuotesFromRealm();
                break;
            }
        }

        for (StockItem item : mMarketIndexList) {
            if (neCode.contains(item.netEaseCode())) {
                item.rebuildTickQuotesFromRealm();
                break;
            }
        }

        for (StockItem item : mProfileIndexStockList) {
            if (neCode.contains(item.netEaseCode())) {
                item.rebuildTickQuotesFromRealm();
                break;
            }
        }
    }
}
